package shujia.day16;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
    线程池：将来主要的作用是加快用户的访问速度，提高固定时间内的访问量。

    java中的线程池种类有很多，不同的线程池，将来线程的调用执行的方式不同。
8c837b154cf1b1797fb1afee6378d75b
    使用工具类创建线程池对象：Executors
                                newCachedThreadPool()
                         【常用】newFixedThreadPool(int nThreads) 创建一个线程池，该线程池重用固定数量的从共享无界队列中运行的线程。
                                newScheduledThreadPool(int corePoolSize) 创建一个线程池，可以调度命令在给定的延迟之后运行，或定期执行。
                                newSingleThreadExecutor() 创建一个使用从无界队列运行的单个工作线程的执行程序。
                                newWorkStealingPool() 创建使用所有 available processors作为其目标并行级别的工作窃取线程池。

    创建线程的三种方式：
        1、继承Thread类，重写run方法，直接new就创建线程对象了，调用start()方法启动
        2、实现Runnable接口，实现run方法，需要借助Thread类创建线程对象，调用start()方法启动
        3、实现Callable接口，借助线程池中的submit方法提交启动


    Runnable接口和Callable接口的区别：
        其中实现Runnable接口和实现Callable接口区别在于，Runnable接口中是实现run方法，run方法没有返回值
        而Callable接口中是实现call方法，call方法可以有返回值的，将来如果一个线程执行完毕后需要返回结果，那么就使用Callable接口
        借助线程池的方式实现多线程。
 */
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i=1;i<=200;i++){
            System.out.println(Thread.currentThread().getName()+" - "+i);
        }
    }
}

class MyCallable implements Callable{

    @Override
    public Object call() throws Exception {
        for (int i=1;i<=200;i++){
            System.out.println(Thread.currentThread().getName()+" - "+i);
        }

        return null;
    }
}

public class ThreadPoolDemo1 {
    public static void main(String[] args) {
        //创建一个固定大小的线程池
        ExecutorService pool = Executors.newFixedThreadPool(2);

        //将线程放入到线程池中运行
        //Future<?> submit(Runnable task) 提交一个可运行的任务执行，并返回一个表示该任务的未来。
//        pool.submit(new MyRunnable()); //底层是使用一个Thread类将其封装成线程对象，启动 // pool-1-thread-1
//        pool.submit(new MyRunnable()); //底层是使用一个Thread类将其封装成线程对象，启动 // pool-1-thread-2
//        pool.submit(new MyRunnable()); //底层是使用一个Thread类将其封装成线程对象，启动

        //<T> Future<T> submit(Callable<T> task) 提交值返回任务以执行，并返回代表任务待处理结果的Future。
//        pool.submit(new MyCallable());
//        pool.submit(new MyCallable());
//        pool.submit(new MyCallable());


        //使用匿名内部类，来提交线程到线程池，不同的线程内部可以是不同的实现。
        pool.submit(new Runnable() {
            @Override
            public void run() {
                // 运行代码逻辑1
            }
        });

        pool.submit(new Runnable() {
            @Override
            public void run() {
                // 运行代码逻辑2
            }
        });



        //线程池需要手动关闭
        pool.shutdown();


    }
}
